/**
 * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.achartengine.chart;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import org.achartengine.model.CategorySeries;
import org.achartengine.model.Point;
import org.achartengine.model.SeriesSelection;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.util.RectFData;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;

/**
 * The pie chart rendering class.
 */
public class PieChart extends RoundChart
{
	/** Handles returning values when tapping on PieChart. */
	private PieMapper mPieMapper;
	
	/**
	 * Builds a new pie chart instance.
	 * 
	 * @param dataset the series dataset
	 * @param renderer the series renderer
	 */
	public PieChart(CategorySeries dataset, DefaultRenderer renderer)
	{
		super(dataset, renderer);
		mPieMapper = new PieMapper();
	}
	
	/**
	 * The graphical representation of the pie chart.
	 * 
	 * @param canvas the canvas to paint to
	 * @param x the top left x value of the view to draw to
	 * @param y the top left y value of the view to draw to
	 * @param width the width of the view to draw to
	 * @param height the height of the view to draw to
	 * @param paint the paint
	 */
	@Override
	public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint)
	{
		paint.setAntiAlias(mRenderer.isAntialiasing());
		paint.setStyle(Style.FILL);
		paint.setStrokeWidth(1.0F);
		paint.setTextSize(mRenderer.getLabelsTextSize());
		int legendSize = getLegendSize(mRenderer, height / 5, 0);
		int left = x;
		int top = y;
		int right = x + width;
		int sLength = mDataset.getItemCount();
		double total = 0;
		String[] titles = new String[sLength];
		for (int i = 0; i < sLength; i++)
		{
			total += mDataset.getValue(i);
			titles[i] = mDataset.getCategory(i);
		}
		if (mRenderer.isFitLegend())
		{
			legendSize = drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize,
					paint, true);
		}
		int bottom = y + height - legendSize;
		drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);
		
		float currentAngle = mRenderer.getStartAngle();
		int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));
		int radius = (int) (mRadius * 0.35 * mRenderer.getScale());
		
		if (mCenterX == NO_VALUE)
		{
			mCenterX = (left + right) / 2;
		}
		if (mCenterY == NO_VALUE)
		{
			mCenterY = (bottom + top) / 2;
		}
		
		// Hook in clip detection after center has been calculated
		mPieMapper.setDimensions(radius, mCenterX, mCenterY);
		boolean loadPieCfg = !mPieMapper.areAllSegmentPresent(sLength);
		if (loadPieCfg)
		{
			mPieMapper.clearPieSegments();
		}
		
		float shortRadius = radius * 0.9f;
		float longRadius = radius * 1.1f;
		
		RectF oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY + radius);
		List<RectF> prevLabelsBounds = new ArrayList<RectF>();
		float[] arrayOfFloat = { 0.0F, 0.4F, 0.8F, 0.9F, 1.0F };
		int[][] arrayOfInt = createGradialColors(true);
		int[][] mArrayOfInt = new int[sLength][];
		for (int i = 0; i < sLength; i++)
		{
			mArrayOfInt[i] = arrayOfInt[i % arrayOfInt.length];
		}
		
		for (int i = 0; i < sLength; i++)
		{
			float value = (float) mDataset.getValue(i);
			float angle = (float) (value / total * 360);
			DecimalFormat mFormat = new DecimalFormat("0.00");
			String percent = mFormat.format(100 * value / total).toString() + "%";
			ShapeDrawable drawable = new ShapeDrawable(new OvalShape());
			Paint paint2 = drawable.getPaint();
			paint2.setShader(new RadialGradient(mCenterX, mCenterY, radius, mArrayOfInt[i], arrayOfFloat,
					Shader.TileMode.MIRROR));
			drawable.setBounds(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY + radius);
			paint.setColor(mArrayOfInt[i][0]);
			// canvas.drawArc(oval, currentAngle, angle, true, paint);
			canvas.drawArc(oval, currentAngle, angle, true, paint2);
			drawLabel(canvas, percent, mRenderer, prevLabelsBounds, mCenterX, mCenterY, shortRadius,
					longRadius, currentAngle, angle, left, right, mArrayOfInt[i][0], paint, true);
			if (mRenderer.isDisplayValues())
			{
				drawLabel(canvas, getLabel(mDataset.getValue(i)), mRenderer, prevLabelsBounds, mCenterX,
						mCenterY, shortRadius / 2, longRadius / 2, currentAngle, angle, left, right,
						mRenderer.getLabelsColor(), paint, false);
			}
			
			// Save details for getSeries functionality
			if (loadPieCfg)
			{
				mPieMapper.addPieSegment(i, value, currentAngle, angle);
			}
			float startAngle = currentAngle;
			currentAngle += angle;
			RectFData mData = new RectFData();
			mData.add2List(radius, currentAngle, startAngle, mCenterX, mCenterY,
					getLabel(mDataset.getValue(i)));
		}
		prevLabelsBounds.clear();
		pieDrawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, mArrayOfInt,
				paint, false);
		drawTitle(canvas, x, y, width, paint);
	}
	
	public SeriesSelection getSeriesAndPointForScreenCoordinate(Point screenPoint)
	{
		return mPieMapper.getSeriesAndPointForScreenCoordinate(screenPoint);
	}
	
	private int[][] createGradialColors(boolean paramBoolean)
	{
		int[] arrayOfInt1 = new int[5];
		arrayOfInt1[0] = Color.rgb(197, 61, 56);
		arrayOfInt1[1] = Color.rgb(181, 56, 52);
		arrayOfInt1[2] = Color.rgb(171, 53, 48);
		arrayOfInt1[3] = Color.rgb(136, 42, 39);
		arrayOfInt1[4] = Color.rgb(99, 29, 27);
		int[] arrayOfInt2 = new int[5];
		arrayOfInt2[0] = Color.rgb(255, 100, 100);
		arrayOfInt2[1] = Color.rgb(230, 100, 100);
		arrayOfInt2[2] = Color.rgb(200, 100, 100);
		arrayOfInt2[3] = Color.rgb(180, 100, 100);
		arrayOfInt2[4] = Color.rgb(160, 100, 100);
		int[] arrayOfInt3 = new int[5];
		arrayOfInt3[0] = Color.rgb(124, 167, 0);
		arrayOfInt3[1] = Color.rgb(111, 149, 0);
		arrayOfInt3[2] = Color.rgb(100, 133, 0);
		arrayOfInt3[3] = Color.rgb(79, 105, 0);
		arrayOfInt3[4] = Color.rgb(60, 79, 0);
		int[] arrayOfInt4 = new int[5];
		arrayOfInt4[0] = Color.rgb(100, 255, 100);
		arrayOfInt4[1] = Color.rgb(100, 230, 100);
		arrayOfInt4[2] = Color.rgb(100, 200, 100);
		arrayOfInt4[3] = Color.rgb(100, 180, 100);
		arrayOfInt4[4] = Color.rgb(100, 160, 100);
		int[] arrayOfInt5 = new int[5];
		arrayOfInt5[0] = Color.rgb(55, 175, 208);
		arrayOfInt5[1] = Color.rgb(49, 155, 186);
		arrayOfInt5[2] = Color.rgb(44, 142, 169);
		arrayOfInt5[3] = Color.rgb(36, 112, 134);
		arrayOfInt5[4] = Color.rgb(26, 85, 100);
		int[] arrayOfInt6 = new int[5];
		arrayOfInt6[0] = Color.rgb(100, 100, 255);
		arrayOfInt6[1] = Color.rgb(100, 100, 230);
		arrayOfInt6[2] = Color.rgb(100, 100, 200);
		arrayOfInt6[3] = Color.rgb(100, 100, 180);
		arrayOfInt6[4] = Color.rgb(100, 100, 160);
		int[] arrayOfInt7 = new int[5];
		arrayOfInt7[0] = Color.rgb(196, 100, 196);
		arrayOfInt7[1] = Color.rgb(180, 100, 180);
		arrayOfInt7[2] = Color.rgb(160, 100, 160);
		arrayOfInt7[3] = Color.rgb(140, 100, 140);
		arrayOfInt7[4] = Color.rgb(120, 100, 120);
		int[] arrayOfInt8 = new int[5];
		arrayOfInt8[0] = Color.rgb(122, 88, 163);
		arrayOfInt8[1] = Color.rgb(108, 78, 144);
		arrayOfInt8[2] = Color.rgb(99, 71, 134);
		arrayOfInt8[3] = Color.rgb(81, 57, 107);
		arrayOfInt8[4] = Color.rgb(57, 40, 75);
		int[] arrayOfInt9 = new int[5];
		arrayOfInt9[0] = Color.rgb(234, 141, 41);
		arrayOfInt9[1] = Color.rgb(213, 128, 38);
		arrayOfInt9[2] = Color.rgb(186, 113, 33);
		arrayOfInt9[3] = Color.rgb(150, 91, 27);
		arrayOfInt9[4] = Color.rgb(111, 68, 20);
		int[] arrayOfInt10 = new int[5];
		arrayOfInt10[0] = Color.rgb(255, 255, 100);
		arrayOfInt10[1] = Color.rgb(230, 230, 100);
		arrayOfInt10[2] = Color.rgb(200, 200, 100);
		arrayOfInt10[3] = Color.rgb(180, 180, 100);
		arrayOfInt10[4] = Color.rgb(160, 160, 100);
		int[] arrayOfInt11 = new int[5];
		arrayOfInt11[0] = Color.rgb(159, 196, 226);
		arrayOfInt11[1] = Color.rgb(142, 176, 202);
		arrayOfInt11[2] = Color.rgb(129, 158, 183);
		arrayOfInt11[3] = Color.rgb(112, 137, 158);
		arrayOfInt11[4] = Color.rgb(78, 96, 110);
		int[] arrayOfInt12 = new int[5];
		arrayOfInt12[0] = Color.rgb(179, 216, 246);
		arrayOfInt12[1] = Color.rgb(162, 196, 222);
		arrayOfInt12[2] = Color.rgb(149, 178, 203);
		arrayOfInt12[3] = Color.rgb(132, 157, 178);
		arrayOfInt12[4] = Color.rgb(98, 116, 130);
		int[] arrayOfInt13 = new int[5];
		arrayOfInt13[0] = Color.rgb(0, 127, 127);
		arrayOfInt13[1] = Color.rgb(0, 112, 112);
		arrayOfInt13[2] = Color.rgb(0, 103, 103);
		arrayOfInt13[3] = Color.rgb(0, 80, 80);
		arrayOfInt13[4] = Color.rgb(0, 46, 46);
		int[] arrayOfInt14 = new int[5];
		arrayOfInt14[0] = Color.rgb(0, 147, 147);
		arrayOfInt14[1] = Color.rgb(0, 132, 132);
		arrayOfInt14[2] = Color.rgb(0, 123, 123);
		arrayOfInt14[3] = Color.rgb(0, 100, 100);
		arrayOfInt14[4] = Color.rgb(0, 66, 66);
		int[][] arrayOfInt15 = { arrayOfInt1, arrayOfInt3, arrayOfInt5, arrayOfInt8, arrayOfInt9,
				arrayOfInt11, arrayOfInt13 };
		int[][] arrayOfInt16 = { arrayOfInt2, arrayOfInt4, arrayOfInt6, arrayOfInt7, arrayOfInt10,
				arrayOfInt12, arrayOfInt14 };
		int[][] arrayOfInt17 = arrayOfInt16;
		if (paramBoolean)
		{
			arrayOfInt17 = arrayOfInt15;
		}
		return arrayOfInt17;
	}
}
